libhttp.mrc

LibHTTP, small yet powerful library to simplify the use of HTTP in scripts.

Takes care of proxies, authentication, URL parsing, making the actual request, parsing headers, and following redirects (HTTP-redirects only). After this "boring" work is complete, LibHTTP transfers control back to the calling script, giving you full freedom to do whatever your need to do with the data. All headers will have been consumed at this point - the data you get from the socket with sockread is the document, without headers. LibHTTP accomplishes this by opening the socket with a different [temporary] name, and renaming it back to what you specified after it has finished its task.

Right click status window and select "Config HTTP Proxy" to do just that. The dialog should be clear enough for end users to understand but if you already have a config dialog in your script you may want to move the options there instead. Proxy support is automatic and transparent: making and handling the requests works exactly the same way whether or not a proxy is used - your script doesn't need to do anything special for proxies to work.

/http_get SOCKETNAME %URL
on *:sockread:SOCKETNAME {
    [read data and do things with it]
}


Errors are communicated with signal (replace "SocketName" in the signal name):
on *:signal:HttpErr_SocketName: /echo -s HTTP connection error: $1-

This signal is triggered if

The socket is automatically closed if any of these errors occur, meaning your custom sockread and sockclose event handlers are never executed. The reverse of this also guaranteed - if your sockread handler is executed you can 100% sure everything went ok. You don't have to catch and handle the error signal, but in most cases you should do it, at least to echo the message to status window. Without any kind of error message users will have no idea what is going wrong and how to fix it.

Of course you still need to test for $sockerr in the sockread and sockclose events, just like you have to with any other socket. LibHTTP detects errors only while connecting and reading headers - after this all control, including responsibilty to detect and handle errors, is yours.


Note: You can not use /sockmark with connections opened by LibHTTP, the library uses the mark for storing various data.

/set %libhttp.debug 1 - enables some debugging messages. Unset to disable.




Exported Alias Summary

boolean sockfree(sockname)
Test whether Sockname is already in use
void http_get(sockname, url)
Request one file from remote server
int httpsock(sockname, [n]) .rcvd .redirects .percent .size
Retrieve special information about Sockname

Local Alias Summary

String lhttp_parse_url(url)
Parses URL and returns a space separated list of URL-components, suitable for input to /http_get
void lhttp_sockopen(finalname, redirects, host, port, path, [user], [pass])
This is what actually opens the connection
void lhttp_process_reply(sockname)
Headers have been read, determine the next step
void lhttp_timeout(sockname)
30 second timeout for the temp-socket
void lhttp_proxytest()
Test proxy address by attempting to connect to it

Event Summary

on *:sockopen:LIBHTTP_TEMP_*: { *
Writes the HTTP-request to socket
on *:sockread:LIBHTTP_TEMP_*: { *
Read and save headers
on *:sockclose:LIBHTTP_TEMP_*: { *
Connection closed while we were still reading headers
on *:dialog:ProxyConfig:init:0: { *
Proxy configuration dialog init
on *:dialog:ProxyConfig:sclick:1: { *
User toggled the "Use Proxy" checkbox
on *:dialog:ProxyConfig:edit:*: { *
User edited one of the four text inputs
on *:sockopen:LIBHTTP_PROXYTEST: { *
Show result of the proxy test
on *:UNLOAD: { *
Unset global variables used by libhttp

sockfree *

boolean sockfree(sockname)

Test whether Sockname is already in use. The normal test 'if ($sock(SOCKNAME) != $null)' is not enough because /http_get opens the sockets using temporary names (these are later renamed to the final form). $sockfree will also check the temporary names to see if there is a socket that will soon be renamed to Sockname.

Parameters:
sockname - The socket name to test
Returns:
$true if Socketname is free, $false if not

http_get *

void http_get(sockname, url)

Request one file from remote server.

Parameters:
sockname - Name for this connections
url - Location of the file
Returns:
-

httpsock *

int httpsock(sockname, [n]) .rcvd .redirects .percent .size

Retrieve special information about Sockname. Uses same syntax as mIRC's $sock(...).property, meaning you can specify wildcard Sockname and select Nth match by passing a second param. This alias works only with sockets opened by /http_get, and even then only after the connection has been handed over to the calling script (IOW, when your on:sockread has run at least once).

Parameters:
sockname - Socket name or wildcard
[n] - Select Nth wildcard match
Properties:
.rcvd - Number of bytes received, not counting HTTP-headers
.redirects - Number of redirects followed (usually 0)
.percent - Percent done, available only if .size is known
.size - Size of the file (value of the Content-Lenght header). Server does not know in advance the size for dynamic content so this works only with static files.
Returns:
Numeric value, $null if the value isn't known (size/percent)

lhttp_parse_url *

String lhttp_parse_url(url)

Parses URL and returns a space separated list of URL-components, suitable for input to /http_get.

Parameters:
url - The url to parse
Returns:
Host Port Path [User] [Pass]

lhttp_sockopen *

void lhttp_sockopen(finalname, redirects, host, port, path, [user], [pass])

This is what actually opens the connection. http_get is really just a wrapper, this where the magic happens. The point of having a wrapper is to be able to change this API without breaking existing programs. Programs use the public, very simple API of the wrapper that never changes, internally we have this more complex and freely changable thing.

The socket is opened with a temporary name, LIBTTP_TEMP_[number]. A hash table of the same name is also created, it is used for storing both request and response headers plus other misc data LibHTTP uses. The hashtable is automatically hfreed if an error occurs, or when control is handed over to user (socket is renamed).

Parameters:
finalname - The final name for this connections
redirects - Number of redirects followed so far
host - Hostname or IP-address of the server
port - Port to connect to (usually 80)
path - Path of the requested resource
[user] - Username (if the server requires one)
[pass] - Password (if the server requires one)
Returns:
-

lhttp_process_reply *

void lhttp_process_reply(sockname)

Headers have been read, determine the next step. If server replied with code 200, rename the socket and hand over control. If the server replied with code 301 or 302 AND sent a Location: header, follow the redirect and close current connection. If the server replied with any other code, signal an error.

Parameters:
sockname -
Returns:
-

lhttp_timeout *

void lhttp_timeout(sockname)

30 second timeout for the temp-socket. If server doesn't respond within 30 seconds of sending the request, or if the connection goes idle for more than 30 sec while reading headers, close the socket and signal an error.

Parameters:
sockname -
Returns:
-

lhttp_proxytest *

void lhttp_proxytest()

Test proxy address by attempting to connect to it

Returns:
-